using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace HenIT.GACCompare
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.Text = "Global Assembly Cache comparison tool - " + Application.ProductVersion.ToString();
            if (Properties.Settings.Default.NewVersion)
            {
                Properties.Settings.Default.Upgrade();
                Properties.Settings.Default.NewVersion = false;
                Properties.Settings.Default.Save();
            }

            if (Properties.Settings.Default.PreviousMachineList == null)
                Properties.Settings.Default.PreviousMachineList = new System.Collections.Specialized.StringCollection();

            foreach (string machineName in Properties.Settings.Default.PreviousMachineList)
            {
                if (!cboMachine1.Items.Contains(machineName.ToUpper()))
                    cboMachine1.Items.Add(machineName.ToUpper());
                if (!cboMachine2.Items.Contains(machineName.ToUpper()))
                    cboMachine2.Items.Add(machineName.ToUpper());
            }
        }

        private void AddPreviousMachine(string machineName)
        {
            if (! Properties.Settings.Default.PreviousMachineList.Contains(machineName))
            {
                Properties.Settings.Default.PreviousMachineList.Add(machineName.ToUpper());
                foreach (string machine in Properties.Settings.Default.PreviousMachineList)
                {
                    if (!cboMachine1.Items.Contains(machineName.ToUpper()))
                        cboMachine1.Items.Add(machineName.ToUpper());
                    if (!cboMachine2.Items.Contains(machineName.ToUpper()))
                        cboMachine2.Items.Add(machineName.ToUpper());
                }
                Properties.Settings.Default.Save();
            }
        }

        private void cmdCompare_Click(object sender, EventArgs e)
        {
            if (cboMachine1.Text.Length == 0)
            {
                MessageBox.Show("Please specify the first computer!", "Computer 1", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
            if (cboMachine2.Text.Length == 0)
            {
                MessageBox.Show("Please specify the second computer!", "Computer 2", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
            AddPreviousMachine(cboMachine1.Text);
            AddPreviousMachine(cboMachine2.Text);
            if (cboMachine1.Text == cboMachine2.Text)
            {
                MessageBox.Show("You cannot compare a computer to itself?", "Compare", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            else
            {

                int assembliesFound = 0;
                richTextBox1.Text = "";
                try
                {
                    Cursor.Current = Cursors.WaitCursor;
                    GACList gacList1 = new GACList();
                    gacList1.LoadList(cboMachine1.Text, txtFilter.Text + "*");
                    GACList gacList2 = new GACList();
                    gacList2.LoadList(cboMachine2.Text, txtFilter.Text + "*");

                    AddFormatRTFLine("Unique assemblies on " + cboMachine1.Text, FontStyle.Bold);
                    List<GACEntry> gacList = gacList1.GetUnique(gacList2.Assemblies);
                    System.Collections.Generic.SortedList<string, GACEntry> gacSortedList = new SortedList<string, GACEntry>();
                    foreach (GACEntry gacEntry in gacList)
                    {
                        if (!gacSortedList.ContainsKey(gacEntry.ToString()))
                            gacSortedList.Add(gacEntry.ToString(), gacEntry);
                    }
                    foreach (GACEntry gacEntry in gacSortedList.Values)
                    {
                        AddFormatRTFLine(gacEntry.ToString(), FontStyle.Regular);
                        if (chkPaths.Checked)
                        {
                            foreach (string assemblyPath in gacEntry.AssemblyPath)
                            {
                                if (assemblyPath.EndsWith(".dll") || assemblyPath.EndsWith(".exe"))
                                    AddFormatRTFLine("   " + assemblyPath + " / " + (gacEntry.FileSize / 1024).ToString() + "KB", FontStyle.Regular);
                            }
                        }
                        assembliesFound++;
                    }
                    AddFormatRTFLine(assembliesFound.ToString() + " entry(s) found", FontStyle.Italic);
                    AddFormatRTFLine("", FontStyle.Regular);

                    AddFormatRTFLine("Unique assembly versions on " + cboMachine1.Text, FontStyle.Bold);
                    gacList = gacList1.GetUniqueVersion(gacList2.Assemblies);
                    gacSortedList = new SortedList<string, GACEntry>();
                    foreach (GACEntry gacEntry in gacList)
                    {
                        if (!gacSortedList.ContainsKey(gacEntry.ToString()))
                            gacSortedList.Add(gacEntry.ToString(), gacEntry);
                    }
                    assembliesFound = 0;
                    foreach (GACEntry gacEntry in gacSortedList.Values)
                    {
                        AddFormatRTFLine(gacEntry.ToString(), FontStyle.Regular);
                        if (chkPaths.Checked)
                        {
                            foreach (string assemblyPath in gacEntry.AssemblyPath)
                            {
                                if (assemblyPath.EndsWith(".dll") || assemblyPath.EndsWith(".exe"))
                                    AddFormatRTFLine("   " + assemblyPath + " / " + (gacEntry.FileSize / 1024).ToString() + "KB", FontStyle.Regular);
                            }
                        }
                        assembliesFound++;
                    }
                    AddFormatRTFLine(assembliesFound.ToString() + " entry(s) found", FontStyle.Italic);
                    AddFormatRTFLine("", FontStyle.Regular);

                    AddFormatRTFLine("Unique assemblies on " + cboMachine2.Text, FontStyle.Bold);
                    gacList = gacList2.GetUnique(gacList1.Assemblies);
                    gacSortedList = new SortedList<string, GACEntry>();
                    foreach (GACEntry gacEntry in gacList)
                    {
                        if (!gacSortedList.ContainsKey(gacEntry.ToString()))
                            gacSortedList.Add(gacEntry.ToString(), gacEntry);
                    }
                    assembliesFound = 0;
                    foreach (GACEntry gacEntry in gacSortedList.Values)
                    {
                        AddFormatRTFLine(gacEntry.ToString(), FontStyle.Regular);
                        if (chkPaths.Checked)
                        {
                            foreach (string assemblyPath in gacEntry.AssemblyPath)
                            {
                                if (assemblyPath.EndsWith(".dll") || assemblyPath.EndsWith(".exe"))
                                    AddFormatRTFLine("   " + assemblyPath + " / " + (gacEntry.FileSize / 1024).ToString() + "KB", FontStyle.Regular);
                            }
                        }
                        assembliesFound++;
                    }
                    AddFormatRTFLine(assembliesFound.ToString() + " entry(s) found", FontStyle.Italic);
                    AddFormatRTFLine("", FontStyle.Regular);

                    AddFormatRTFLine("Unique assembly versions on " + cboMachine2.Text, FontStyle.Bold);
                    gacList = gacList2.GetUniqueVersion(gacList1.Assemblies);
                    gacSortedList = new SortedList<string, GACEntry>();
                    foreach (GACEntry gacEntry in gacList)
                    {
                        if (!gacSortedList.ContainsKey(gacEntry.ToString()))
                            gacSortedList.Add(gacEntry.ToString(), gacEntry);
                    }
                    assembliesFound = 0;
                    foreach (GACEntry gacEntry in gacSortedList.Values)
                    {
                        AddFormatRTFLine(gacEntry.ToString(), FontStyle.Regular);
                        if (chkPaths.Checked)
                        {
                            foreach (string assemblyPath in gacEntry.AssemblyPath)
                            {
                                if (assemblyPath.EndsWith(".dll") || assemblyPath.EndsWith(".exe"))
                                    AddFormatRTFLine("   " + assemblyPath + " / " + (gacEntry.FileSize / 1024).ToString() + "KB", FontStyle.Regular);
                            }
                        }
                        assembliesFound++;
                    }
                    AddFormatRTFLine(assembliesFound.ToString() + " entry(s) found", FontStyle.Italic);

                }
                catch (Exception ex)
                {
                    AddFormatRTFLine(ex.ToString(), FontStyle.Bold);
                }
                finally
                {
                    Cursor.Current = Cursors.Default;
                }
            }
        }
        
        private void cmdList1_Click(object sender, EventArgs e)
        {
            if (cboMachine1.Text.Length == 0)
            {
                MessageBox.Show("Please specify the first computer!", "Computer 1", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
            ListAssembies(cboMachine1.Text);
            AddPreviousMachine(cboMachine1.Text);
        }

        private void cmdList2_Click(object sender, EventArgs e)
        {
            if (cboMachine2.Text.Length == 0)
            {
                MessageBox.Show("Please specify the second computer!", "Computer 1", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
            ListAssembies(cboMachine2.Text);
            AddPreviousMachine(cboMachine2.Text);
        }

        private void ListAssembies(string machine)
        {
            int assembliesFound = 0;
            richTextBox1.Text = "";
            try
            {
                Cursor.Current = Cursors.WaitCursor;
                GACList gacList1 = new GACList();
                gacList1.LoadList(machine, txtFilter.Text + "*");
                SortedList<string, GACEntry> gacSortedList = new SortedList<string, GACEntry>();
                foreach (GACEntry gacEntry in gacList1.Assemblies)
                {
                    if (!gacSortedList.ContainsKey(gacEntry.ToString()))
                        gacSortedList.Add(gacEntry.ToString(), gacEntry);
                }

                AddFormatRTFLine("Listing assemblies on " + machine, FontStyle.Bold);
                foreach (GACEntry gacEntry in gacSortedList.Values)
                {
                    AddFormatRTFLine(gacEntry.ToString(), FontStyle.Regular);
                    if (chkPaths.Checked)
                    {
                        foreach (string assemblyPath in gacEntry.AssemblyPath)
                        {
                            if (assemblyPath.EndsWith(".dll") || assemblyPath.EndsWith(".exe"))
                                AddFormatRTFLine("   " + assemblyPath, FontStyle.Regular);
                        }
                    }
                    assembliesFound++;
                }
                AddFormatRTFLine(assembliesFound.ToString() + " entry(s) found", FontStyle.Italic);
            }
            catch (Exception ex)
            {
                AddFormatRTFLine(ex.ToString(), FontStyle.Bold);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        private void AddFormatRTFLine(string text, FontStyle fs)
        {
            richTextBox1.AppendText(text);
            if (text.Length > 0)
            {
                richTextBox1.SelectionStart = richTextBox1.Text.Length - text.Length;
                richTextBox1.SelectionLength = text.Length;
                richTextBox1.SelectionFont = new Font("Microsoft Sans Serif", 8, fs);
            }
            richTextBox1.AppendText("\r\n");
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            richTextBox1.Copy();
        }

        private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            richTextBox1.SelectAll(); 
        }

        private void saveOutputToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (richTextBox1.Text.Length > 0)
            {
                if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    richTextBox1.SaveFile(saveFileDialog1.FileName, RichTextBoxStreamType.RichText);
                }
            }
        }

        private void richTextBox1_LinkClicked(object sender, LinkClickedEventArgs e)
        {
            if (MessageBox.Show("Do you want to open the containing folder?", "Open folder", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                //System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo();
                //psi.FileName = "Explorer.exe";
                //psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
                //psi.Arguments = "/e,/idlist," + System.IO.Path.GetDirectoryName(e.LinkText);

                System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(e.LinkText));
            }
        }
    }
}